package com.yami.shop.personnft.api.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yami.shop.bean.dto.ShareIsUnreceive;
import com.yami.shop.bean.enums.SceneType;
import com.yami.shop.bean.event.UpdateRightsEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.ImageUtil;
import com.yami.shop.common.util.Json;
import com.yami.shop.common.util.StringUtils;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.personnft.common.dao.PersonNftApplyMapper;
import com.yami.shop.personnft.common.dto.PersonShareDto;
import com.yami.shop.personnft.common.model.PersonNft;
import com.yami.shop.personnft.common.model.PersonShare;
import com.yami.shop.personnft.common.model.PersonShareReceive;
import com.yami.shop.personnft.common.model.PersonShareRecord;
import com.yami.shop.personnft.common.service.PersonNftService;
import com.yami.shop.personnft.common.service.PersonShareReceiveService;
import com.yami.shop.personnft.common.service.PersonShareRecordService;
import com.yami.shop.personnft.common.service.PersonShareService;
import com.yami.shop.personnft.common.vo.PersonNftDtailfVo;
import com.yami.shop.personnft.common.vo.PersonShareVo;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.*;
import com.yami.shop.user.common.model.UserGasLog;
import com.yami.shop.user.common.service.UserGasInfoService;
import com.yami.shop.user.common.service.UserGasLogService;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 持仓分享接口
 */

@Slf4j
@RestController("personShareController")
@RequestMapping("/dtc/app/personShare")
@Tag(name = "app-personnft分享信息")
@AllArgsConstructor
public class PersonShareController {

    @Autowired
    private PersonNftService personNftService;
    @Autowired
    private UserGasInfoService userGasInfoService;
    @Autowired
    private PersonShareService personShareService;
    @Autowired
    private PersonShareRecordService personShareRecordService;
    @Autowired
    private PersonShareReceiveService personShareReceiveService;
    @Autowired
    private PersonNftApplyMapper personNftApplyMapper;
    @Autowired
    private ProductService productService;
    @Autowired
    private UserService userService;
    @Autowired
    private ProdNftService prodNftService;
    @Autowired
    private ChannelUserRelationRecordService channelUserRelationRecordService;
    @Autowired
    private ShopConfig shopConfig;
    @Autowired
    private UserGasLogService userGasLogService;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private PersonConfigService personConfigService;

    @GetMapping("/ua/getShareDetail")
    public ServerResponseEntity<PersonShareVo> getShareDetail(Long shareId){
        PersonShareVo personShareVo = new PersonShareVo();
        // 获取分享信息
        PersonShare personShare = personShareService.getById(shareId);
        personShareVo.setShareId(personShare.getId());
        personShareVo.setBlessing(personShare.getBlessing());
        personShareVo.setStatus(personShare.getStatus());
        personShareVo.setVoiceUrl(personShare.getVoiceUrl());
        personShareVo.setVoiceTime(personShare.getVoiceTime());
        personShareVo.setPurchaseStatus(0);
        // 获取商品信息
        Product productByProdId = productService.getProductByProdId(personShare.getProductId());
        personShareVo.setLinkAddr(productByProdId.getLinkAddr());
        if(productByProdId.getStatus() == 1 || productByProdId.getStatus() == 9){
            personShareVo.setPurchaseStatus(1);
        }
        personShareVo.setPic(productByProdId.getPic());
        if(ObjectUtil.isNotEmpty(personShare.getImgUrl())){
            personShareVo.setPic(personShare.getImgUrl());
        }
        personShareVo.setProdName(productByProdId.getProdName());
        // 获取用户信息
        User userByUserId = userService.getUserByUserId(personShare.getUserId());
        personShareVo.setRealmName(userByUserId.getRealName());
        personShareVo.setRealmPic(userByUserId.getPic());
        personShareVo.setNickName(userByUserId.getNickName());
        personShareVo.setColorData(personShare.getColorData());
        return ServerResponseEntity.success(personShareVo);
    }

    @PostMapping("/shareCheck")
    public ServerResponseEntity<Integer> shareCheck(@RequestBody PersonShareDto personShareDto){
        String userId = SecurityUtils.getUser().getUserId();
        // 查询持仓数据、数据校验
        List<Long> longs = Arrays.asList(21L,25L);
        PersonNft personNft = PersonNft.builder().userId(userId).denomId(personShareDto.getDemonId()).status(0).notSceneType(longs).build();
        List<PersonNft> personNfts = personNftService.listByParam(personNft);
        // 排除已经分享过的token
        String mall4JChannel = shopConfig.getMall4JChannel();
        List<String> recordTokens = personShareRecordService
                .list(new QueryWrapper<PersonShareRecord>().eq("denom_id", personShareDto.getDemonId()).ne("status", 2))
                .stream().map(PersonShareRecord::getTokensId)
                .collect(Collectors.toList());
        if(ObjectUtil.isNotEmpty(recordTokens)){
            personNfts = personNfts.stream().filter(s -> !recordTokens.contains(s.getTokenId())).collect(Collectors.toList());
            personNfts = personNfts.stream().filter(s -> !(StrUtil.isNotEmpty(mall4JChannel) && StringUtils.matches(s.getChannelCode(), Arrays.asList(mall4JChannel.split(","))))).collect(Collectors.toList());
        }
        return ServerResponseEntity.success(personNfts.size());
    }

    // 分享接口
    @PostMapping("/sharePerson")
    @Transactional
    public ServerResponseEntity<Long> sharePerson(@RequestBody PersonShareDto personShareDto){

        String userId = SecurityUtils.getUser().getUserId();
        // 查询持仓数据、数据校验
        List<Long> longs = Arrays.asList(21L,25L);
        PersonNft personNft = PersonNft.builder().userId(userId).denomId(personShareDto.getDemonId()).status(0).notSceneType(longs).build();
        List<PersonNft> personNfts = personNftService.listByParam(personNft);
        // 排除已经分享过的token
        List<String> recordTokens = personShareRecordService
                .list(new QueryWrapper<PersonShareRecord>().eq("denom_id", personShareDto.getDemonId()).ne("status", 2))
                .stream().map(PersonShareRecord::getTokensId)
                .collect(Collectors.toList());
        if(ObjectUtil.isNotEmpty(recordTokens)){
            String mall4JChannel = shopConfig.getMall4JChannel();
            personNfts = personNfts.stream().filter(s -> !recordTokens.contains(s.getTokenId())).collect(Collectors.toList());
            personNfts = personNfts.stream().filter(s -> !(StrUtil.isNotEmpty(mall4JChannel) && StringUtils.matches(s.getChannelCode(), Arrays.asList(mall4JChannel.split(","))))).collect(Collectors.toList());
        }
        if(personShareDto.getShareNum() > personNfts.size()){
            return ServerResponseEntity.showFailMsg("可分享数量不能大于"+personNfts.size());
        }
        // 获取商品信息
        ProdNft dataByProdId = prodNftService.getDataByProdId(personNfts.get(0).getProductId());
        if(dataByProdId.getBlessingNumber() != 0 && dataByProdId.getBlessingNumber() < personShareDto.getBlessing().length()){
            return ServerResponseEntity.showFailMsg("分享内容字数过多");
        }

        // 扣gas
        userGasInfoService.reduceGasNumberByUserId(userId, personShareDto.getShareNum());

        // 新增分享主表
        PersonShare personShare = PersonShare.builder()
                .personNum(personShareDto.getShareNum())
                .chainCode(personNfts.get(0).getChainCode())
                .productId(personNfts.get(0).getProductId())
                .status(0)
                .blessing(personShareDto.getBlessing())
                .voiceUrl(personShareDto.getVoiceUrl())
                .stock(personShareDto.getShareNum())
                .expirationTime(DateUtil.offsetDay(new Date(), 1).toTimestamp())
                .userId(userId)
                .colorData(personShareDto.getColorData())
                .voiceTime(personShareDto.getVoiceTime())
                .build();
//        if(ObjectUtil.isNotEmpty(dataByProdId.getCoordinate())){
//            Product productByProdId = productService.getProductByProdId(personShare.getProductId());
//            String[] coordinates = dataByProdId.getCoordinate().split(",");
//            String minioConfig = sysConfigService.getValue("MINIO_OSS_CONFIG");
//            Map map = Json.parseObject(minioConfig, Map.class);
//            String imageRoot = (String) map.get("endpoint");
//            String imageFile = (String) map.get("bucketName");
//            MultipartFile multipartFile = ImageUtil.writeImage(imageRoot+"/"+imageFile+"/"+productByProdId.getPic(), personShareDto.getBlessing(), Integer.parseInt(coordinates[0]), Integer.parseInt(coordinates[1]),personShareDto.getColorData());
//            try {
//                String fileName = attachFileService.uploadFile(multipartFile.getBytes(), UUID.fastUUID()+".jpg");
//                personShare.setImgUrl(fileName);
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
        personShareService.save(personShare);
        List<PersonNft> freezePerson = personNfts.subList(0, personShareDto.getShareNum());
        String contenStr = freezePerson.stream().map(PersonNft::getTokenId).collect(Collectors.joining(","));
        String dawProductCode = freezePerson.stream().map(PersonNft::getDawProductCode).collect(Collectors.joining(","));
        // 冻结持仓、新增持仓记录
        String applyId = IdUtil.getSnowflake().nextIdStr();
        PersonNftApply personNftAccount = PersonNftApply.builder()
                .sceneType(SceneType.ShareFreeze.getCode())
                .content(contenStr)
                .status(1)
                .dawProductCode(dawProductCode)
                .denomId(freezePerson.get(0).getDenomId())
                .chainCode(freezePerson.get(0).getChainCode())
                .channelCode(freezePerson.get(0).getChannelCode())
                .channelType("1")
                .createTime(DateUtil.date())
                .id(applyId)
                .userId(userId)
                .count(personShareDto.getShareNum())
                .productId(freezePerson.get(0).getProductId())
                .remark(personShare.getId() + "")
                .build();
        personNftApplyMapper.save(personNftAccount);
        // 2、冻结持仓
        freezePerson.forEach(s->s.setStatus(1));
        personNftService.updateBatch(freezePerson);
        // 新增分享持仓数据
        List<PersonShareRecord> personShareRecords = new ArrayList<>();
        for(PersonNft person : freezePerson){
            PersonShareRecord personShareRecord = PersonShareRecord.builder()
                    .shareId(personShare.getId() + "")
                    .applyId(applyId)
                    .productCode(person.getDawProductCode())
                    .denomId(person.getDenomId())
                    .productId(person.getProductId())
                    .tokensId(person.getTokenId())
                    .status(0).build();
            personShareRecords.add(personShareRecord);
        }
        personShareRecordService.saveBatch(personShareRecords);

        // DTC++ gas 记录保存
        UserGasLog userGasLog = new UserGasLog();
        userGasLog.setCreateTime(new Date());
        userGasLog.setIoType(0); // 收支类型 0支出 1收入
        userGasLog.setType(8);   // gas记录 类型
        userGasLog.setIsPayed(1);  // 0未支付
        userGasLog.setUserId(userId);
        userGasLog.setGasId(personShare.getId());
        userGasLog.setTabStatus(1); //已处理--- 已发送
        userGasLog.setPateTab(personShare.getChainCode());  //平台
        userGasLog.setGasNum(Integer.parseInt(personShare.getPersonNum()+""));
        userGasLogService.save(userGasLog);
        return ServerResponseEntity.success(personShare.getId());
    }

    /**
     * 分享领取
     * @param shareId
     * @return
     */
    @GetMapping("shareReceive")
    public ServerResponseEntity<ShareIsUnreceive> shareReceive(Long shareId){
        ShareIsUnreceive shareIsUnreceive = new ShareIsUnreceive();
        String userId = SecurityUtils.getUser().getUserId();
        // 查询 分享状态、剩余个数
        PersonShare personShare = personShareService.getById(shareId);
        Product productByProdId = productService.getProductByProdId(personShare.getProductId());
        shareIsUnreceive.setChannelCode(productByProdId.getChannelCode());
        shareIsUnreceive.setChain(personShare.getChainCode());
        if(personShare.getUserId().equals(userId)){
            shareIsUnreceive.setMsg("无法领取自己的分享");
            shareIsUnreceive.setStatus(0);
            return ServerResponseEntity.success(shareIsUnreceive);
        }
        if(personShare.getStatus() == 1){
            shareIsUnreceive.setMsg("领取完了");
            shareIsUnreceive.setStatus(0);
            return ServerResponseEntity.success(shareIsUnreceive);
        }
        if(personShare.getStatus() == 2){
            shareIsUnreceive.setMsg("分享结束");
            shareIsUnreceive.setStatus(0);
            return ServerResponseEntity.success(shareIsUnreceive);
        }

        if(ObjectUtil.isEmpty(SecurityUtils.getUser().getXsUserId())){
            shareIsUnreceive.setMsg("未实名无法领取分享");
            shareIsUnreceive.setStatus(0);
            return ServerResponseEntity.success(shareIsUnreceive);
        }
        // 获取商品信息
        Product product = productService.getProductByProdId(personShare.getProductId());
        Boolean hasAllAddress = channelUserRelationRecordService.isHasAllAddress(userId, product.getChain(), product.getChannelCode(), "1");
        if (!hasAllAddress) {
            shareIsUnreceive.setMsg(I18nMessage.getMessage("yami.dtc.redpacket.open.check"));
            shareIsUnreceive.setStatus(0);
            shareIsUnreceive.setIsHasDTCAddress(hasAllAddress);
            return ServerResponseEntity.success(shareIsUnreceive);
        }

        // 查询 是否领取过
        QueryWrapper<PersonShareReceive> personShareReceiveQueryWrapper = new QueryWrapper<>();
        personShareReceiveQueryWrapper.eq("share_id",shareId);
        personShareReceiveQueryWrapper.eq("user_id",userId);
        personShareReceiveQueryWrapper.ne("status",2);
        PersonShareReceive personShareReceive = personShareReceiveService.getOne(personShareReceiveQueryWrapper);
        if(ObjectUtil.isNotEmpty(personShareReceive)){
            shareIsUnreceive.setMsg("您已经领取过该分享");
            shareIsUnreceive.setStatus(0);
            return ServerResponseEntity.success(shareIsUnreceive);
        }
        // 领取、获取币、新增 领取记录
        QueryWrapper<PersonShareRecord> personShareRecordQueryWrapper = new QueryWrapper<>();
        personShareRecordQueryWrapper.eq("share_id",shareId);
        personShareRecordQueryWrapper.eq("status",0);
        personShareRecordQueryWrapper.last("limit 1");
        PersonShareRecord one = personShareRecordService.getOne(personShareRecordQueryWrapper);
        if(ObjectUtil.isEmpty(one)){
            shareIsUnreceive.setMsg("领取完了");
            shareIsUnreceive.setStatus(0);
            return ServerResponseEntity.success(shareIsUnreceive);
        }
        // 修改剩余数量
        if(personShare.getStock() == 1){
            personShare.setStatus(1);
        }
        personShare.setStock(personShare.getStock() - 1);
        personShareService.updateById(personShare);
        PersonShareReceive build = PersonShareReceive.builder().productCode(one.getProductCode()).productId(one.getProductId()).tokensId(one.getTokensId()).userId(userId).status(0).shareId(shareId).build();
        personShareReceiveService.save(build);

        // 修改状态
        one.setStatus(1);
        personShareRecordService.updateById(one);
        shareIsUnreceive.setMsg("领取成功");
        shareIsUnreceive.setStatus(1);

        // 分享领取权益修改
        applicationContext.publishEvent(new UpdateRightsEvent(one.getTokensId(), personShare.getUserId(), userId));

        return ServerResponseEntity.success(shareIsUnreceive);
    }

    @GetMapping("/shareAppreciateCheck")
    public ServerResponseEntity shareAppreciateCheck(@RequestParam String tokenId){
        String userId = SecurityUtils.getUser().getUserId();
        PersonNft personNft = PersonNft.builder().userId(userId).tokenId(tokenId).build();
        PersonNftDtailfVo oneDetail = personNftService.getOneDetail(personNft);
        if(ObjectUtil.isNull(oneDetail)){
            return ServerResponseEntity.success(false);
        }
        if(2 == oneDetail.getAttr() || 1 == oneDetail.getAttr() ){
            return ServerResponseEntity.success(true);
        }
        return ServerResponseEntity.success(false);
    }
    // 分享鉴赏接口
    @PostMapping("/sharePersonAppreciate")
    @Transactional
    public ServerResponseEntity<Long> sharePersonAppreciate(@RequestBody PersonShareDto personShareDto){
        String userId = SecurityUtils.getUser().getUserId();
        PersonNft personNft = PersonNft.builder().userId(userId).tokenId(personShareDto.getTokenId()).build();
        List<PersonNft> personNfts = personNftService.listByParam(personNft);
        PersonNft person = personNfts.get(0);
        //配置表
        PersonConfig personConfig = new PersonConfig();
        personConfig.setBusinessType("2");//2分享鉴赏
        personConfig.setSourceType("2");//1系统2用户
        personConfig.setDenomId(person.getDenomId());
        personConfig.setProdId(person.getProductId());
        personConfig.setCount(1);
        personConfig.setPaymentType(personShareDto.getGasNum()==0?"1":"2");//1免费2付费
        personConfig.setGasNum(personShareDto.getGasNum());
        personConfig.setCreateTime(new Date());
        personConfig.setChainCode(person.getChainCode());
        personConfigService.save(personConfig);
        // 新增分享主表
        PersonShare personShare = PersonShare.builder()
                .personNum(1)
                .status(0)
                .userId(userId)
                .productId(person.getProductId())
                .chainCode(person.getChainCode())
                .type("2")//2分享鉴赏
                .personConfigId(personConfig.getPersonnftConfigId())
                .build();
        personShareService.save(personShare);
        //分享详情表
        PersonShareRecord personShareRecord = PersonShareRecord.builder()
                .shareId(personShare.getId() + "")
                .productCode(person.getDawProductCode())
                .denomId(person.getDenomId())
                .productId(person.getProductId())
                .tokensId(person.getTokenId())
                .status(3).build();
        personShareRecordService.save(personShareRecord);
        return ServerResponseEntity.success(personShare.getId());
    }

    /**
     * 分享鉴赏领取
     * @param shareId outId
     * @return
     */
    @GetMapping("shareReceiveAppreciate")
    public ServerResponseEntity shareReceiveAppreciate(@RequestParam Long shareId,@RequestParam Long outId){
        String userId = SecurityUtils.getUser().getUserId();
        // 查询 分享状态、剩余个数
        PersonShare personShare = personShareService.getById(shareId);
        PersonConfig byId = personConfigService.getById(personShare.getPersonConfigId());
        PersonShareRecord one = personShareRecordService.getOne(new QueryWrapper<PersonShareRecord>().lambda().eq(PersonShareRecord::getShareId, shareId));
        // 查询 是否领取过
        QueryWrapper<PersonShareReceive> personShareReceiveQueryWrapper = new QueryWrapper<>();
        personShareReceiveQueryWrapper.eq("share_id",shareId);
        personShareReceiveQueryWrapper.eq("user_id",userId);
        personShareReceiveQueryWrapper.eq("status",1);
        PersonShareReceive personShareReceive = personShareReceiveService.getOne(personShareReceiveQueryWrapper);
        if(ObjectUtil.isNotEmpty(personShareReceive)){
            throw new YamiShopBindException("您已经购买过该分享了");
        }
        if("2".equals(byId.getPaymentType()) &&  !userId.equals(personShare.getUserId())){//付费
            //扣除领取人
            userGasLogService.reduceGasNumberThansferByUserId(userId,byId.getGasNum(),11,null,null,null);
            //分享者增加gas
            userGasLogService.saveGasNumberThansferByUserId(personShare.getUserId(),byId.getGasNum(),11,null,null,null);
        }
        PersonShareReceive build = PersonShareReceive.builder().productCode(one.getProductCode()).productId(one.getProductId()).tokensId(one.getTokensId()).userId(userId).status(1).shareId(shareId).outId(outId).build();
        personShareReceiveService.save(build);
        return ServerResponseEntity.success();
    }


    /**
     * 分享鉴赏详情
     * @param shareId
     * @return
     */
    @GetMapping("shareAppreciateDetail")
    public ServerResponseEntity shareAppreciateDetail(@RequestParam Long shareId){
        String userId = SecurityUtils.getUser().getUserId();
        // 查询 分享付费类型，token详情，是否购买分享含源文件
        PersonShare personShare = personShareService.getById(shareId);
        PersonConfig byId = personConfigService.getById(personShare.getPersonConfigId());
        PersonShareRecord one = personShareRecordService.getOne(new QueryWrapper<PersonShareRecord>().lambda().eq(PersonShareRecord::getShareId, shareId));

        PersonNft personNft = PersonNft.builder().tokenId(one.getTokensId()).build();
        PersonNftDtailfVo oneDetail = personNftService.getOneDetail(personNft);
        JSONObject res = new JSONObject();
        res.put("denomId",one.getDenomId());
        res.put("prodId",one.getProductId());
        res.put("tokenId",one.getTokensId());
        res.put("productCode",one.getProductCode());
        res.put("gas",byId.getGasNum());
        res.put("chainCode",byId.getChainCode());
        res.put("paymentType",byId.getPaymentType());
        res.put("productName",oneDetail.getDawName());
        res.put("productImg",oneDetail.getPicImg());
        res.put("attr",oneDetail.getAttr());
        res.put("authorImg",oneDetail.getAuthorImg());
        res.put("authorName",oneDetail.getAuthor());
        res.put("issueName",oneDetail.getShopName());
        //是否领取过
        QueryWrapper<PersonShareReceive> personShareReceiveQueryWrapper = new QueryWrapper<>();
        personShareReceiveQueryWrapper.eq("share_id",shareId);
        personShareReceiveQueryWrapper.eq("user_id",userId);
        personShareReceiveQueryWrapper.eq("status",1);
        PersonShareReceive personShareReceive = personShareReceiveService.getOne(personShareReceiveQueryWrapper);
        res.put("isReceive",false);
        if(!ObjectUtil.isNull(personShareReceive)){
            res.put("isReceive",true);
            //获取源文件
            if(ObjectUtil.isNotEmpty(oneDetail.getSourceUrl())){
                res.put("dawUri",oneDetail.getSourceUrl());
            }else{
                com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(oneDetail.getDawUri());
                res.put("dawUri",jsonObject.get("sourceFile"));
            }
        }
        return ServerResponseEntity.success(res);
    }
}
